import serial
import math
import os
import serial.tools.list_ports
import re
from collections import Counter
import random
import numpy as np
import xlrd
import xlwt
from xlutils.copy import copy
import time

plist = list(serial.tools.list_ports.comports())

# 第6个参数为是否按小值来作为最终测量结果
def getData(frontPort, backPort, setRange=[], limit1 = 0, limit2 = 0, isGetMin=False):
    # print('measureRange is from ' + str(setRange[0]) + 'mm to ' + str(setRange[1]) + 'mm, limit1 and limit2 is ' + str(
    #     limit1) + ',' + str(limit2))
    w = []
    d1Arr = []
    d2Arr = []
    pArr = []
    # leftLimit = setRange[0]
    # rightLimit = setRange[1]
    ser1 = serial.Serial(frontPort, 115200, timeout=0.5)
    ser2 = serial.Serial(backPort, 115200, timeout=0.5)
    for i in range(200):
        try:
            s = str(ser1.readline())
            s = s.split(',')
            d = s[0]
            p = s[1]
            d = d.replace("b'Distance=  ", '')
            p1 = p.replace("peak= ", '')
            p1 = p1.replace("peak=", '')
            p1 = p1.replace("Peak=", '')
            p1 = p1.replace("\\n'", '')
            d1 = int(d)
            # if d1 > limit1:
            d1Arr.append(d1)

            s = str(ser2.readline())
            s = s.split(',')
            d = s[0]
            p = s[1]
            d = d.replace("b'Distance=  ", '')
            p2 = p.replace("peak= ", '')
            p2 = p2.replace("peak=", '')
            p2 = p2.replace("Peak=", '')
            p2 = p2.replace("\\n'", '')
            d2 = int(d)
            # if d2 > limit2:
            d2Arr.append(d2)
            pArr.append((int(p1) + int(p2)) / 2)

            w.append(frameworkDis - d1 - d2)
        except ValueError:
            continue

    ser1.close()
    ser2.close()
    # 筛选合规值

    # return w, pArr

    # print('beforeFilter:', w)
    # filterW = []
    # for j in range(len(w)):
    #     if w[j] > leftLimit and w[j] < rightLimit:
    #         filterW.append(w[j])
    # print('afterFilter:', filterW)

    sigmaFilterData = sigmaFilter(w)
    # print('afterSigmaFilter:', sigmaFilterData)
    # return  filterW

    if len(sigmaFilterData) > 0:
        if not isGetMin:
            # 测量值按出现频率取加权平均
            # r = Counter(a).most_common(1)[0][0]
            # counter = Counter(sigmaFilterData).most_common()
            # print('counter', counter)

            # 修改为取均值之上的数据为合理测量值的策略
            averageVal = np.average(sigmaFilterData)
            filterData = []
            for i in range(len(sigmaFilterData)):
                if sigmaFilterData[i] > averageVal:
                    filterData.append(sigmaFilterData[i])
            counter = Counter(filterData).most_common()
            elements = []
            weights = []
            for key, value in counter:
                elements.append(key)
                weights.append(value)
            measureValue = np.average(elements, weights=weights)
            # print('measureValue:', measureValue)
            return measureValue, w, pArr, d1Arr, d2Arr
        else:
            return min(sigmaFilterData), w, pArr, d1Arr, d2Arr
    else:
        print('thers is some wrong with 红外测距，是不是穿了黑色衣服')


def write_excel_xls(path, sheet_name, value):
    index = len(value)  # 获取需要写入数据的行数
    workbook = xlwt.Workbook()  # 新建一个工作簿
    sheet = workbook.add_sheet(sheet_name)  # 在工作簿中新建一个表格
    for i in range(0, index):
        for j in range(0, len(value[i])):
            sheet.write(i, j, value[i][j])  # 像表格中写入数据（对应的行和列）
    workbook.save(path)  # 保存工作簿
    print("xls格式表格写入数据成功！")


def write_excel_xls_append(path, value):
    try:
        index = len(value)  # 获取需要写入数据的行数
        workbook = xlrd.open_workbook(path)  # 打开工作簿
        sheets = workbook.sheet_names()  # 获取工作簿中的所有表格
        worksheet = workbook.sheet_by_name(sheets[0])  # 获取工作簿中所有表格中的的第一个表格
        rows_old = worksheet.nrows  # 获取表格中已存在的数据的行数
        new_workbook = copy(workbook)  # 将xlrd对象拷贝转化为xlwt对象
        new_worksheet = new_workbook.get_sheet(0)  # 获取转化后工作簿中的第一个表格
        for i in range(0, index):
            for j in range(0, len(value[i])):
                new_worksheet.write(i + rows_old, j, value[i][j])  # 追加写入数据，注意是从i+rows_old行开始写入
        new_workbook.save(path)  # 保存工作簿
        print("xls格式表格【追加】写入数据成功！")
    except FileNotFoundError:
        write_excel_xls(path, sheetname, value)

def sigmaFilter (arr):
    arr = np.array(arr)
    diffArr = arr - np.mean(arr)
    sigma = ((np.sum(diffArr ** 2) / diffArr.shape[0])) ** 0.5
    # print(sigma)
    filterArr = []
    for i in range(len(arr)):
        if abs(diffArr[i]) < sigma:
            filterArr.append(arr[i])
    return filterArr

def getLaserWidth(frontPort, backPort):
    w = []
    d1Arr = []
    d2Arr = []
    ser1 = serial.Serial(frontPort, 9600, timeout=0.5)
    ser2 = serial.Serial(backPort, 9600, timeout=0.5)
    for i in range(10):
        try:
            d = str(ser1.readline())
            d = d.replace("b'", '')
            d = d.replace("mm\\r\\n'", '')
            # print(d)
            d1 = int(d)
            d1Arr.append(d1)

            d = str(ser2.readline())
            d = d.replace("b'", '')
            d = d.replace("mm\\r\\n'", '')
            d2 = int(d)
            d2Arr.append(d2)

            w.append(laserFrameworkDis - d1 - d2)
        except ValueError:
            continue

    ser1.close()
    ser2.close()

    # 测量值按出现频率取加权平均
    # r = Counter(a).most_common(1)[0][0]
    counter = Counter(w).most_common()
    d1Value = Counter(d1Arr).most_common(1)[0][0]
    d2Value = Counter(d2Arr).most_common(1)[0][0]
    # print('counter', counter)
    elements = []
    weights = []
    for key, value in counter:
        elements.append(key)
        weights.append(value)
    measureValue = np.average(elements, weights=weights)
    print('Laser measureValue:', measureValue)
    return int(measureValue), d1Value, d2Value


frontPort = 'com27'
backPort = 'com2'
laserFrontPort = 'com8'
laserBackPort = 'com16'
filename = "dataFile/widthMeasureData" + str(random.uniform(0, 1)) + '.xls'
sheetname = 'widthData'
frameworkDis = 941

laserFrameworkDis = 907
index = 1

while True:
    temp = input('按回车测量\n')
    time.sleep(2)
    # 获取测量范围
    # laserWidth, d1, d2 = getLaserWidth(laserFrontPort, laserBackPort)

    # valueRange = [laserWidth - 30, laserWidth + 30]
    # valueRange = [150, laserWidth + 100]
    # testData, dataset =
    # dataset, pset = getData(frontPort, backPort, valueRange, d1, d2)
    if temp == '1':
        value, dataset, pset, d1, d2 = getData(frontPort, backPort, isGetMin=True)
        print('凹陷部位处理！')
        print('测量值为： ' + str(value))
        print(dataset)
        print()
    else:
        value, dataset, pset, d1, d2 = getData(frontPort, backPort)
        print('测量值为： ' + str(value))
        print(dataset)
        # print(pset)
        # print(value)
    for i in range(len(dataset)):
        dataset[i] = [dataset[i], pset[i], d1[i], d2[i]]
    # print(dataset)
    write_excel_xls(filename, sheetname, dataset)
    # write_excel_xls_append(filename, dataset)

    # writeValue = [[index, testData]]
    # index = index + 1
    # write_excel_xls_append(filename, writeValue)